#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QLocale>

#include <plugin/command/ConsoleLogCommand.h>
#include <plugin/util/Framework.h>

namespace antu
{
namespace plugin
{
Framework::Framework()
    : m_pSettingsManager(nullptr),
      m_pDescriptionManager(nullptr),
      m_pLoggerService(nullptr),
      m_pSiteManager(nullptr)
{
}

bool Framework::loadTranslationFile(const QString &translationFile)
{
    Q_ASSERT( this->context() != nullptr );

    QFileInfo info(translationFile);
    if (info.isAbsolute())
    {
        QString completeName = QString("%1_%2").arg(translationFile).arg(QLocale::system().name());
        bool result = m_oTranslator.load(completeName);
        qApp->installTranslator(&m_oTranslator);
        return result;
    }
    else
    {
        QDir dir(this->context()->languagePath());
        QString translateFileName = QString("%1_%2").arg(translationFile).arg(QLocale::system().name());
        bool result = m_oTranslator.load(dir.filePath(translateFileName));
        qApp->installTranslator(&m_oTranslator);
        return result;
    }
}

Framework::~Framework()
{
    delete this->m_pSettingsManager;
    delete this->m_pDescriptionManager;
    delete this->m_pLoggerService;
    delete this->m_pSiteManager;
}

void Framework::setup(PluginContext *pContext, AbstractSecurityContextHandler *pHandler)
{
    Q_ASSERT(pContext != nullptr);

    this->m_pPluginContext = pContext;
    if (pHandler == nullptr)
        this->m_pSecurityHandler = new NullSecurityContextHandler;
    else
        this->m_pSecurityHandler = pHandler;

    // create settings defaults
    QCoreApplication::setOrganizationName("Antu OSGi for Qt");
    QCoreApplication::setOrganizationDomain("osgi.antu.com");
    QCoreApplication::setApplicationName(pContext->applicationName());

    // register logger service
    this->m_pLoggerService = new LoggerService();

    QDir path(qApp->applicationDirPath());
    this->m_pSettingsManager = new QSettings(path.absoluteFilePath("global_settings.ini"), QSettings::IniFormat);

    QString logLevel = this->m_pSettingsManager->value("logger/level", "debug").toString();
    this->m_pLoggerService->setLogLevel(logLevel);
    this->m_pLoggerService->setLogCommand(new ConsoleLogCommand);

    this->m_pDescriptionManager = new PluginDescriptionManager();
    this->m_pDescriptionManager->init(pContext->applicationGroup(), pContext->pluginPath());

    this->loadTranslationFile("plugin");
}

AbstractSecurityContextHandler *Framework::securityContextHandler()
{
    return this->m_pSecurityHandler;
}

LoggerService *Framework::logger()
{
    return this->m_pLoggerService;
}

QSettings *Framework::settingsManager()
{
    return this->m_pSettingsManager;
}

PluginDescriptionManager *Framework::descriptionManager()
{
    return this->m_pDescriptionManager;
}

SiteManager *Framework::siteManager()
{
    return this->m_pSiteManager;
}

void Framework::setLogCommand(AbstractLogCommand *pCommand)
{
    Q_ASSERT(pCommand != nullptr);

    if (this->m_pLoggerService != nullptr)
        this->m_pLoggerService->setLogCommand(pCommand);
}

PluginContext *Framework::context()
{
    return this->m_pPluginContext;
}

bool Framework::loadTranslationFile(QTranslator &translator, const QString &translationFile)
{
    Q_ASSERT( this->context() != nullptr );

    QFileInfo info(translationFile);
    if (info.isAbsolute())
    {
        QString completeName = QString("%1_%2").arg(translationFile).arg(QLocale::system().name());
        bool result = translator.load(completeName);
        qApp->installTranslator(&translator);
        return result;
    }
    else
    {
        QDir dir(this->context()->languagePath());
        QString translateFileName = QString("%1_%2").arg(translationFile).arg(QLocale::system().name());
        bool result = translator.load(dir.filePath(translateFileName));
        qApp->installTranslator(&translator);
        return result;
    }
}

void Framework::stop(CloseSignal* pSignal)
{
    Q_ASSERT(pSignal != nullptr);
    emit aboutToClose(pSignal);
}

Framework Framework::Instance;

CloseSignal::CloseSignal()
{
    this->m_bCanClose = true;
}

bool CloseSignal::canClose()
{
    return this->m_bCanClose;
}

void CloseSignal::setCanClose(bool canClose)
{
    if (this->m_bCanClose)
        this->m_bCanClose = canClose;
}

}
}

